package com.sigmazero13.bgjeeves.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import com.sigmazero13.bgjeeves.R;

public class ImportExportDatabaseFileTask extends AsyncTask<String, Void, OperationResult> {
	private final ProgressDialog dialog;
	private Context parentContext;
	private String importFilename;
	private String command = "Export";
	private TaskDoneListener listener;
	private final SimpleDateFormat TIMESTAMP = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
	
	public ImportExportDatabaseFileTask(Context parentContext, TaskDoneListener listener, String importFilename) {
		super();
		dialog = new ProgressDialog(parentContext);
		this.parentContext = parentContext;
		this.listener = listener;
		this.importFilename = importFilename;
		if (importFilename != null) {
			command = "Import";
		}
	}

	// can use UI thread here
	protected void onPreExecute() {
		this.dialog.setMessage(command + " database...");
		this.dialog.show();
	}

	// automatically done on worker thread (separate from UI thread)
	protected OperationResult doInBackground(final String... args) {
		
		String packageName = parentContext.getString(R.string.app_package);
		String dbFileName = parentContext.getString(R.string.db_file);

		File dbFile = new File(Environment.getDataDirectory()
				+ "/data/" + packageName + "/databases/" + dbFileName);

		File toFile, fromFile;
		
		File exportDir = new File(parentContext.getString(R.string.db_backup_loc));
		if (!exportDir.exists()) {
			exportDir.mkdirs();
		}
		
		if (importFilename == null) {
			fromFile = dbFile;
			
			String backupFileName = dbFileName + "." + TIMESTAMP.format(new Date());
			toFile = new File(exportDir, backupFileName);
		} else {
			toFile = dbFile;
			fromFile = new File(exportDir, importFilename);
		}

		try {
			this.copyAllDbFiles(fromFile, toFile);
			return OperationResult.OPERATION_OK;
		} catch (IOException e) {
			Log.e("com.sigmazero13.bgjeeves.utils.ExportDatabaseFileTask", e.getMessage(), e);
			return OperationResult.OPERATION_FAIL;
		}
	}
	
	// can use UI thread here
	protected void onPostExecute(final OperationResult result) {
		if (this.dialog.isShowing()) {
			this.dialog.dismiss();
		}
		if (OperationResult.OPERATION_OK == result) {
			listener.taskDone("import");
			Toast.makeText(parentContext, command + " successful!", Toast.LENGTH_SHORT).show();
		} else {
			Toast.makeText(parentContext, command + " failed", Toast.LENGTH_SHORT).show();
		}
	}

	private void copyFile(File src, File dst) throws IOException {
		dst.delete();
		dst.createNewFile();
		FileChannel inChannel = new FileInputStream(src).getChannel();
		FileChannel outChannel = new FileOutputStream(dst).getChannel();
		try {
			inChannel.transferTo(0, inChannel.size(), outChannel);
		} finally {
			if (inChannel != null)
				inChannel.close();
			if (outChannel != null)
				outChannel.close();
		}
	}
	
	private void copyAllDbFiles(File src, File dst) throws IOException {
		String [] addons = {"", "-shm", "-wal"};
		
		for (String addon : addons) {
			File copyFrom = new File(src.getCanonicalPath() + addon);
			File copyTo = new File(dst.getCanonicalPath() + addon);
			if (copyFrom.exists()) {
				copyFile(copyFrom, copyTo);
			} else {
				copyTo.delete();
			}
		}
	}

}